﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Cpuss
{
    /// <summary>
    /// Logs the results of a simulation to a database.
    /// </summary>
    public class Logger
    {
        private readonly string _connectionString;
        private readonly List<Run> _runs;

        /// <summary>
        /// Creates and initializes a new <see cref="Logger"/> instance.
        /// </summary>
        /// <param name="connectionString">Connection string to use to connect to the database.</param>
        public Logger(string connectionString)
        {
            _connectionString = connectionString;
            _runs = new List<Run>();
        }

        /// <summary>
        /// Gets the connection string being used for the <see cref="Logger"/>.
        /// </summary>
        public string ConnectionString
        {
            get { return _connectionString; }
        }

        /// <summary>
        /// Adds a new runner to a collection to be persisted to a database.
        /// </summary>
        /// <param name="runner">Runner to add to database.</param>
        public void Add(Runner runner)
        {
            if (runner == null)
            {
                throw new ArgumentNullException("runner");
            }

            int small =
                runner.ProcessLoad.Where(
                    x => x.BurstTime >= (int) BurstTime.SmallMin && x.BurstTime <= (int) BurstTime.SmallMax).Count();
            int medium =
                runner.ProcessLoad.Where(
                    x => x.BurstTime >= (int) BurstTime.MediumMin && x.BurstTime <= (int) BurstTime.MediumMax).Count();
            int large =
                runner.ProcessLoad.Where(
                    x => x.BurstTime >= (int) BurstTime.LargeMin && x.BurstTime <= (int) BurstTime.LargeMax).Count();
            _runs.Add(new Run
                          {
                              Id = runner.Id,
                              ProcessCount = runner.ProcessLoad.Count,
                              SmallProcessCount = small,
                              MediumProcessCount = medium,
                              LargeProcessCount = large,
                              AverageWaitTime = runner.GetWaitTimeMean(),
                              Strategy = runner.Strategy
                          });
        }

        /// <summary>
        /// Persists the logged <see cref="Runner"/> objects to the database.
        /// </summary>
        public void SubmitData()
        {
            using (var dcx = new CpussDataContext(_connectionString))
            {
                dcx.Runs.InsertAllOnSubmit(_runs);
                dcx.SubmitChanges();
            }
        }
    }
}